# -*- encoding: UTF-8 -*-

import datetime
import pandas as pd
import simpy
import random

from Airplane import *

class TaxiWaySystem:
    """ 机场滑行道系统
    """
    def __init__(self):
        self.count_airplane = 0

class AirportSimulator:
    """ 机场仿真器主类
    """
    def __init__(
            self, env, 
            num_customer = 600,
            average_arrival_time=600,     # 平均到达时间
            num_runways=2,                # 跑道的数量
            num_parking_bays=8,           # 停机坪的数量
            num_ground_services_groups=2, # 地勤组的数量
            average_landing_time=35/60,   # 降落所需的平均时间
            record_queue_len=False        # 是否记录队长
            ):

        self.env = env
        self.num_customer = num_customer
        self.record_queue_len = record_queue_len
        self.average_arrival_time = average_arrival_time
        self.average_landing_time = average_landing_time

        self.airline_dict = {
            'plane_id' : [],
            'arrival_time' : [],
            'takeoff_time' : [],
            'landing_wait_time' : [],
            'stay_time' : []
        }
        
        if record_queue_len:
            self.keep_record_queue_len = True
            self.queue_len_dict = {
                'time_stamp' : [],
                'runways' : [],
                'parking_bays' : [],
                'ground_services_groups' : []
            }

        self.runways = simpy.PriorityResource(
                env = env, 
                capacity=num_runways
                )
        self.parking_bays = simpy.Resource(
                env = env, 
                capacity=num_parking_bays
                )
        self.ground_services_groups = simpy.Resource(
                env = env, 
                capacity=num_ground_services_groups 
                )

        self.taxi_way_system = TaxiWaySystem()

        self.env.process(
            self.Source()
            )
        
        if record_queue_len:
            self.env.process(
                self.queue_len_recorder()
                )
    
    def queue_len_recorder(self):
        while self.keep_record_queue_len:
            yield self.env.timeout(1)
            self.queue_len_dict['time_stamp'].append(
                self.env.now)
            self.queue_len_dict['runways'].append(
                len(self.runways.queue))
            self.queue_len_dict['parking_bays'].append(
                len(self.parking_bays.queue))
            self.queue_len_dict['ground_services_groups'].append(
                len(self.ground_services_groups.queue))

    def Source(self):
        for id in range(self.num_customer):

            yield self.env.timeout(
                max(
                    1,
                    random.expovariate(
                        1 / self.average_arrival_time
                        )
                    )
                )
    
            self.env.process(
                self.airlineArrivalControl(id)
            )
            id += 1
        if self.record_queue_len:
            self.keep_record_queue_len = False

    def airlineArrivalControl(
            self, airline_id
            ):

        current_flight = Airplane(
            self.env,
            airline_id,
            self,
            average_landing_time=self.average_landing_time,
            )
        
        current_flight.process()
        while current_flight.is_left != True:
            yield self.env.timeout(1)
        
        arrival_time = current_flight.arrival_time
        takeoff_time = current_flight.takeoff_time
        stay_time = takeoff_time - arrival_time
        landing_wait_time = current_flight.landing_wait_time

        self.airline_dict['plane_id'].append(airline_id)
        self.airline_dict['arrival_time'].append(arrival_time)
        self.airline_dict['takeoff_time'].append(takeoff_time)
        self.airline_dict['landing_wait_time'].append(landing_wait_time)
        self.airline_dict['stay_time'].append(stay_time)

    @property
    def result(self):
        res = pd.DataFrame(
            self.airline_dict
        )
        return res
    
    @property
    def queue_len_df(self):
        if self.record_queue_len == False:
            print(
                'queue length not recorded!'
                )
            print(
                'use arg `record_queue_len=True` to start recording'
                )
        else:
            res = pd.DataFrame(
                self.queue_len_dict
                )
            return res
            
